/* Copyright 2012 Tobias Marschall
 * 
 * This file is part of CLEVER.
 * 
 * CLEVER is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * CLEVER is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with CLEVER.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <iostream>
#include <fstream>
#include <vector>
#include <cassert>

#include <boost/program_options.hpp>
#include <boost/unordered_set.hpp>

#include "Variation.h"
#include "VariationUtils.h"
#include "VariationListParser.h"
#include "FastaReader.h"
#include "VersionInfo.h"

using namespace std;
using namespace boost;
namespace po = boost::program_options;

void usage(const char* name, const po::options_description& options_desc) {
	cerr << "Usage: " << name << " [options] <reference.fasta> <variants-file>" << endl;
	cerr << endl;
	cerr << "Reads a list of variations and return a sub-list of it where all redundant variations have been" << endl;
	cerr << "removed, that is, for each equivalence class of variations, only one (the rightmost) variation" << endl;
	cerr << "is retained. Two variations are considered equivalent if applying them to the reference genome" << endl;
	cerr << "yields the same donor genome." << endl;
	cerr << endl;
	cerr << options_desc << endl;
	exit(1);
}


int main(int argc, char* argv[]) {
	VersionInfo::checkAndPrintVersion("remove-redundant-variations", cerr);
	string commandline = VersionInfo::commandline(argc, argv);
	// PARAMETERS

	po::options_description options_desc("Allowed options");
	options_desc.add_options()
//		("significance_level,p", po::value<double>(&significance_level)->default_value(0.05), "Level of evidence necessary NOT to associate read with a enclosed variation.")
	;

	if (argc<3) {
		usage(argv[0], options_desc);
	}
	string reference_filename(argv[argc-2]);
	string variants_filename(argv[argc-1]);
	argc -= 2;

	po::variables_map options;
	try {
		po::store(po::parse_command_line(argc, argv, options_desc), options);
		po::notify(options);
	} catch(std::exception& e) {
		cerr << "error: " << e.what() << "\n";
		return 1;
	}
	cerr << "Commandline: " << commandline << endl;

	ifstream variants_stream(variants_filename.c_str());
	if (variants_stream.fail()) {
		cerr << "Error: could not open \"" << variants_filename << "\"." << endl;
		return 1;
	}
	auto_ptr<vector<Variation> > variations = VariationListParser::parse(variants_stream);
	cerr << "Read " << variations->size() << " variations." << endl;

	auto_ptr<FastaReader::reference_map_t> reference_map = FastaReader::parseFromFile(reference_filename);
	cerr << "Read " << reference_map->size() << " reference sequences." << endl;

	auto_ptr<vector<Variation> > result_list = VariationUtils::removeRedundant(*reference_map, *variations);
	cerr << "Retaining " << result_list->size() << " non-equivalent variations." << endl;

	for (size_t i=0; i<result_list->size(); ++i) {
		cout << result_list->at(i) << endl;
	}
	
	return 0;
}
